home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C ++ / Applications / TimGA 1.2.1 / .cp / CGraphPane.cp < prev    next >
Encoding:
Text File  |  1997-07-16  |  18.5 KB  |  717 lines  |  [TEXT/CWIE]

  1. // ===========================================================================
  2. //    CGraphPane.cp        ©1995-97 Timo Eloranta         All rights reserved.
  3. // ===========================================================================
  4. //    This class displays the best drawing on the screen.
  5.  
  6. #include "CGraphPane.h"
  7. #include "CGraphGAApp.h"
  8. #include "MyUtils.h"
  9. #include "GraphGA_PaneIDs.h"
  10.  
  11. #include <UDrawingState.h>
  12. #include <UGWorld.h>
  13. #include <UModalDialogs.h>
  14. #include <LGAEditField.h>
  15. #include <LWindow.h>
  16. #include <LClipboard.h>
  17. #include <LString.h>
  18. #include <UDesktop.h>
  19.  
  20. Int16    kMaxSquareSizes[70+1] =
  21.  
  22.         {    0,    0, 173,       113,    85,    67,    57,    49,    42,    38,    33,
  23.                 31,    29,        26,    24,    23,    21,    20,    19,    18,    17,
  24.                 16,    15,        15,    14,    14,    13,    12,    12,    12,    11,
  25.                 11,    11,        10,    10,    10,    9,    9,    9,    8,    8,
  26.                 8,    8,        8,    8,    7,    7,    7,    7,    7,    7,
  27.                 6,    6,        6,    6,    6,    6,    6,    6,    5,    5,
  28.                 5,    5,        5,    5,    5,    5,    5,    5,    5,    5    };
  29.  
  30. Int16    kSquareSizes[ ] =
  31.  
  32.         {    5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 
  33.             21, 23, 24, 26, 29, 31, 33, 38, 42, 49, 57, 67, 85, 113, 173 };
  34.  
  35. const    RGBColor    blackRGB    = { 0, 0, 0 };
  36. const    RGBColor    l_greyRGB    = { 0xEEEE, 0xEEEE, 0xEEEE };    // light grey
  37. const    RGBColor    d_greyRGB    = { 0x8000, 0x8000, 0x8000 };    // 50% grey
  38. const     RGBColor    D_greyRGB    = { 0x2000, 0x2000, 0x2000 };    // 87,5% grey
  39. const     RGBColor    goldenRGB    = { 0xFFFF, 0x9C9C, 0x0808 };
  40.  
  41.  
  42. #define _72dpi 0x00480000
  43.  
  44. // ---------------------------------------------------------------------------
  45. //        • CGraphPane
  46. //
  47. //          Called by:    URegistrar::CreateObject
  48. // ---------------------------------------------------------------------------
  49.  
  50. CGraphPane::CGraphPane(
  51.     LStream    *inStream)
  52.         : LView(inStream)
  53. {
  54.     CalcLocalFrameRect( mFrameRect );
  55.     mGWorld = new LGWorld( mFrameRect, 0 );
  56.     
  57.     if (! mGWorld )
  58.         ::StopAlert( ALRT_Offscreen, nil);
  59.  
  60.     mGraph             = nil;
  61.     
  62.     mFullWindow     = true;
  63.     mShowGrid         = true;
  64.     mShowEdges         = true;
  65.     mShowNodes         = true;
  66.     mDarkGrid        = true;
  67.     mUseColor        = true;
  68.     
  69.     mGridSquareSize    = max_Int16;
  70.  
  71.     ToggleMenuItem( cmd_ShowGrid,        str_HideGrid);
  72.     ToggleMenuItem( cmd_ShowEdges,        str_HideEdges);
  73.     ToggleMenuItem( cmd_ShowNodes,        str_HideNodes);
  74.     ToggleMenuItem( cmd_BrightenGrid,    str_BrightenGrid);
  75.     ToggleMenuItem( cmd_BlackAndWhite,    str_ToBlackAndWhite);
  76.         
  77.     ((LWindow *) mSuperView) -> GetStandardSize( mWindStdSize); 
  78. }
  79.  
  80. // ---------------------------------------------------------------------------
  81. //        • ~CGraphPane
  82. // ---------------------------------------------------------------------------
  83. //    Destructor
  84.  
  85. CGraphPane::~CGraphPane()
  86. {
  87.     if ( mGWorld )
  88.         delete mGWorld;
  89. }
  90.  
  91. // ---------------------------------------------------------------------------
  92. //        • ObeyCommand
  93. //
  94. //          Called by:    LCommander::ProcessCommand
  95. // ---------------------------------------------------------------------------
  96. //    Respond to commands
  97.  
  98. Boolean
  99. CGraphPane::ObeyCommand(
  100.     CommandT    inCommand,
  101.     void        *ioParam)
  102. {
  103.     Boolean        cmdHandled = true,
  104.                 bRefreshNeeded = false;
  105.                 
  106.     switch (inCommand) {
  107.     
  108.         case cmd_Copy:
  109.             PlaceInClipboard();    // Place picture of the drawing to clipboard
  110.             break;
  111.  
  112.         case cmd_ShowDrawing:
  113.             mFullWindow = (mFullWindow) ? false : true;
  114.             ((LWindow *) mSuperView) -> SendAESetZoom();
  115.             if (mFullWindow)
  116.                 bRefreshNeeded = true;
  117.             break;
  118.  
  119.         case cmd_ShowGrid:
  120.             mShowGrid = (mShowGrid) ? false : true;
  121.             bRefreshNeeded = true;
  122.             if (mShowGrid)
  123.                     ToggleMenuItem( cmd_ShowGrid, str_HideGrid);
  124.             else    ToggleMenuItem( cmd_ShowGrid, str_ShowGrid);
  125.             break;
  126.  
  127.         case cmd_ShowEdges:
  128.             mShowEdges = (mShowEdges) ? false : true;
  129.             bRefreshNeeded = true;
  130.             if (mShowEdges)
  131.                     ToggleMenuItem( cmd_ShowEdges, str_HideEdges);
  132.             else    ToggleMenuItem( cmd_ShowEdges, str_ShowEdges);
  133.             break;
  134.  
  135.         case cmd_ShowNodes:
  136.             mShowNodes = (mShowNodes) ? false : true;
  137.             bRefreshNeeded = true;
  138.             if (mShowNodes)
  139.                     ToggleMenuItem( cmd_ShowNodes, str_HideNodes);
  140.             else    ToggleMenuItem( cmd_ShowNodes, str_ShowNodes);
  141.             break;
  142.  
  143.         case cmd_BrightenGrid:
  144.             mDarkGrid = (mDarkGrid) ? false : true;
  145.             bRefreshNeeded = true;
  146.             if (mDarkGrid)
  147.                     ToggleMenuItem( cmd_BrightenGrid, str_BrightenGrid);
  148.             else    ToggleMenuItem( cmd_BrightenGrid, str_DarkenGrid);
  149.             break;
  150.  
  151.         case cmd_BlackAndWhite:
  152.             mUseColor = (mUseColor) ? false : true;
  153.             if (mUseColor)
  154.                     ToggleMenuItem( cmd_BlackAndWhite, str_ToBlackAndWhite);
  155.             else    ToggleMenuItem( cmd_BlackAndWhite, str_SwitchToColor);
  156.                 
  157.             InvalidateDrawing( false );
  158.             LPane::Draw( nil );
  159.             break;
  160.             
  161.         case cmd_IncreaseSquareSize:
  162.         case cmd_DecreaseSquareSize:
  163.             mGridSquareSize = 
  164.                 GetNextSquareSize( inCommand == cmd_IncreaseSquareSize );
  165.             mNodeSize = SelectNodeSize();
  166.             CalculateGridRect();
  167.             
  168.             InvalidateDrawing( false );
  169.             LPane::Draw( nil );
  170.             break;
  171.             
  172.         case cmd_SetSquareSize:
  173.             Int32    theSize = mGridSquareSize;
  174.  
  175.             if ( UModalDialogs::AskForOneNumber( 
  176.                     this, WIND_SetSize, edit_SquareSize, theSize )) {
  177.                     // Entry confirmed, set new value
  178.                     
  179.                 if ( ValidSquareSize( theSize ) ) {
  180.                     mGridSquareSize = theSize;
  181.                     mNodeSize = SelectNodeSize();
  182.                     CalculateGridRect();
  183.                     
  184.                     InvalidateDrawing( false );
  185.                     LPane::Draw( nil );
  186.                 } else {
  187.                     LStr255    theParam0( theSize );
  188.                     LStr255 theParam1( (Int32) mApp -> GetGridSize() );
  189.                     LStr255    theParam2( 5L );
  190.                     LStr255 theParam3( (Int32) mMaxSquareSize );
  191.                     UDesktop::Deactivate();
  192.                     ::ParamText( theParam0, theParam1, theParam2, theParam3);
  193.                     ::StopAlert( ALRT_InvalidSquareSize, nil );
  194.                     UDesktop::Activate();
  195.                 }
  196.             }
  197.             break;
  198.         
  199.  
  200.         default:
  201.             cmdHandled = LCommander::ObeyCommand(inCommand, ioParam);
  202.             break;
  203.     }
  204.     
  205.     if (bRefreshNeeded)
  206.         InvalidateDrawing( true );
  207.     
  208.     return cmdHandled;
  209. }
  210.  
  211. // ---------------------------------------------------------------------------
  212. //        • FindCommandStatus
  213. //
  214. //          Called by:    LCommander::ProcessCommandStatus
  215. // ---------------------------------------------------------------------------
  216. //    Determine which menu items will be enabled when we're on duty in the chain
  217. //    of command.
  218.  
  219. void
  220. CGraphPane::FindCommandStatus(
  221.     CommandT    inCommand,
  222.     Boolean        &outEnabled,
  223.     Boolean        &outUsesMark,
  224.     Char16        &outMark,
  225.     Str255        outName)
  226. {
  227.     SDimension16    theCurWindSize;
  228.  
  229.     // Determine whether we currently show the drawing by
  230.     // comparing the current size of the window to the so called
  231.     // standard size, which in our case equals the min size.
  232.     // If the current size is bigger than the std size, the
  233.     // drawing pane is visible/shown/used ...
  234.  
  235.     ((LWindow *) mSuperView) -> GetFrameSize( theCurWindSize );
  236.     mFullWindow = ( theCurWindSize.width > mWindStdSize.width );
  237.  
  238.     outUsesMark = false;        // None of our commands use mark
  239.  
  240.     switch (inCommand) {
  241.  
  242.         case cmd_ShowDrawing:
  243.             if (mFullWindow)
  244.                     ::GetIndString( outName, STRx_Menus, str_HideDrawing);
  245.             else    ::GetIndString( outName, STRx_Menus, str_ShowDrawing);
  246.             outEnabled = true;
  247.             break;
  248.  
  249.         case cmd_Copy:
  250.         case cmd_ShowGrid:
  251.         case cmd_SetSquareSize:
  252.         case cmd_BlackAndWhite:
  253.             outEnabled = mFullWindow;
  254.             break;
  255.  
  256.         case cmd_ShowEdges:
  257.         case cmd_ShowNodes:
  258.             outEnabled = mFullWindow && mGraph;
  259.             break;
  260.  
  261.         case cmd_BrightenGrid:
  262.             outEnabled = mFullWindow && mShowGrid && mUseColor;
  263.             break;
  264.  
  265.         case cmd_IncreaseSquareSize:
  266.             outEnabled = mFullWindow && (mGridSquareSize < mMaxSquareSize);
  267.             break;
  268.  
  269.         case cmd_DecreaseSquareSize:
  270.             outEnabled = mFullWindow && (mGridSquareSize > 5);
  271.             break;
  272.  
  273.         default:
  274.             LCommander::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
  275.             break;
  276.     }
  277. }
  278.  
  279. // ---------------------------------------------------------------------------
  280. //        • SetGraph
  281. //
  282. //          Called by:    CGraphGAApp::InitForNoGraph
  283. //                        CGraphGAApp::ObeyCommand
  284. //                        CGraphGADoc::PrepareToIterate
  285. // ---------------------------------------------------------------------------
  286.  
  287. void
  288. CGraphPane::SetGraph( CGraphPtr inGraph )
  289. {
  290.     Int16    theGridSize;
  291.     
  292.     mGraph            = inGraph;
  293.     theGridSize        = mApp -> GetGridSize();
  294.     mMaxSquareSize    = kMaxSquareSizes[ theGridSize ];
  295.     
  296.     if ( mGridSquareSize > mMaxSquareSize ) {
  297.         mGridSquareSize = mMaxSquareSize;
  298.         mNodeSize        = SelectNodeSize();
  299.     }
  300.     
  301.     InvalidateDrawing( false );
  302. }
  303.  
  304. // ---------------------------------------------------------------------------
  305. //        • InvalidateDrawing
  306. //
  307. //          Called by:    CGraphGADoc::PrepareToIterate
  308. //                        CGraphGADoc::SpendTime
  309. //                        CGraphPane::ObeyCommand
  310. // ---------------------------------------------------------------------------
  311.  
  312. void
  313. CGraphPane::InvalidateDrawing( Boolean inDrawNow)
  314. {
  315.     mDrawingIsOld = true;
  316.     if ( inDrawNow )
  317.         DrawTheBest();
  318. }
  319.  
  320. // ---------------------------------------------------------------------------
  321. //        • PlaceInClipboard (PRIVATE)
  322. //
  323. //          Based on CDDItem.cp::PlaceInClipboard
  324. //          by Gilles Dignard (gdignard@hookup.net)
  325. //
  326. //          Called by:    CGraphPane::ObeyCommand
  327. // ---------------------------------------------------------------------------
  328.  
  329. void
  330. CGraphPane::PlaceInClipboard()
  331. {
  332.     // Find the application's clipboard
  333.  
  334.     LClipboard* theClipboard = LClipboard::GetClipboard();
  335.     SignalIf_( theClipboard == nil );
  336.  
  337.     // Add the picture of the object to the clipboard. The last parameter in 
  338.     // the SetData method indicates that we want the clipboard cleared before
  339.     // the data we're passing in is added to the clipboard.
  340.  
  341.     PicHandle thePicH = CreatePict();
  342.     theClipboard -> SetData('PICT', (Handle) thePicH, true);
  343.     ::KillPicture(thePicH);
  344. }
  345.  
  346. // ---------------------------------------------------------------------------
  347. //        • CreatePict (PRIVATE)
  348. //
  349. //          Create a handle to a pict containing the drawing.
  350. //          
  351. //          The calling procedure is responsible for issuing the
  352. //          KillPicture(PicHandle) needed to clean up after we're done with it.
  353. //
  354. //          Based on CDDItem.cp::CreatePict
  355. //          by Gilles Dignard (gdignard@hookup.net)
  356. //
  357. //          Called by:    CGraphPane::PlaceInClipboard
  358. // ---------------------------------------------------------------------------
  359.  
  360. PicHandle
  361. CGraphPane::CreatePict()
  362. {
  363.     RgnHandle theCurrentClipRgn = ::NewRgn();
  364.     ::GetClip( theCurrentClipRgn );                // Save the current clip region
  365.     
  366.     OpenCPicParams    theOpenParams    = { {    mGridRect.top, 
  367.                                             mGridRect.left,
  368.                                              mGridRect.bottom,
  369.                                              mGridRect.right,    }, 
  370.                                         _72dpi, _72dpi, -2, 0, 0 };
  371.                                         
  372.     PicHandle thePicH    = ::OpenCPicture( &theOpenParams );
  373.     
  374.     ::ClipRect( &mGridRect );
  375.  
  376.     EraseBackground( mGridRect, false );
  377.                                 
  378.         if ( mShowGrid )            //
  379.             DrawGrid();                //    Draw the graph !!
  380.         if ( mGraph ) {                //
  381.             if ( mShowEdges )         //
  382.                 DrawEdges( true );    //
  383.             if ( mShowNodes )        //
  384.                 DrawNodes();        //
  385.         }                            //
  386.  
  387.     ::ClosePicture();
  388.     
  389.     ::SetClip( theCurrentClipRgn );            // Restore the clip region
  390.  
  391.     return thePicH;
  392. }
  393.  
  394. // ---------------------------------------------------------------------------
  395. //        • DrawSelf        (PROTECTED)
  396. //
  397. //          Called by:    LView::Draw
  398. // ---------------------------------------------------------------------------
  399. // Slam the graph drawing from the offscreen to the 'real' screen...
  400.  
  401. void
  402. CGraphPane::DrawSelf()
  403. {
  404.     // If the graph has changed and we still haven't drawn it to
  405.     // the offscreen, we better do it now, unless the drawing is
  406.     // not shown at all...
  407.     
  408.     if ( mDrawingIsOld && mFullWindow ) {
  409.         DrawTheBest();
  410.         FocusDraw();
  411.     }
  412.  
  413.     StColorPenState::Normalize();
  414.     
  415.     if ( mGWorld )
  416.         mGWorld -> CopyImage( GetMacPort(), mFrameRect );
  417. }
  418.  
  419. // ---------------------------------------------------------------------------
  420. //        • DrawTheBest (PRIVATE)
  421. //
  422. //          Called by:    CGraphPane::InvalidateDrawing
  423. //                        CGraphPane::DrawSelf
  424. // ---------------------------------------------------------------------------
  425.  
  426. void
  427. CGraphPane::DrawTheBest()
  428. {
  429.     Rect    theFrame = mFrameRect;
  430.     
  431.     // Draw only, if the drawing is visible...
  432.  
  433.     if ( mFullWindow && mGWorld ) {
  434.     
  435.         FocusDraw();
  436.         StColorPenState    theState;
  437.  
  438.         mGWorld -> BeginDrawing();        // Lets draw the graph...
  439.         
  440.         ::InsetRect( &theFrame, 1, 1 );        // A nice white frame...
  441.  
  442.         CalculateGridRect();
  443.  
  444.         EraseBackground( theFrame, true );    // Black or white background
  445.  
  446.         if ( mShowGrid )            //
  447.             DrawGrid();                //    Draw the graph !!
  448.         if ( mGraph ) {                //
  449.             if ( mShowEdges )         //
  450.                 DrawEdges();        //
  451.             if ( mShowNodes )        //
  452.                 DrawNodes();        //
  453.         }                            //
  454.         
  455.         mGWorld -> EndDrawing();        // We are done with drawing...
  456.                                             
  457.         Rect    pRect = mGridRect;            
  458.         LocalToPortPoint( topLeft( pRect ) );
  459.         LocalToPortPoint( botRight( pRect ) );
  460.         InvalPortRect( &pRect );                // Force update
  461.         
  462.         // We just drew the picture so its not old anymore!
  463.         
  464.         mDrawingIsOld = false;
  465.     }
  466. }
  467.  
  468. // ---------------------------------------------------------------------------
  469. //        • EraseBackground (PRIVATE)
  470. //
  471. //          Called by:    CGraphPane::CreatePict
  472. //                        CGraphPane::DrawTheBest
  473. // ---------------------------------------------------------------------------
  474.  
  475. void
  476. CGraphPane::EraseBackground( Rect &inEraseRect, Boolean inForceErase )
  477. {
  478.     StColorPenState::Normalize();
  479.     
  480.     if ( mUseColor ) {                    // Set back color
  481.         ::RGBBackColor( &blackRGB );
  482.                                         // Else back color is white
  483.         ::EraseRect( &inEraseRect );
  484.     }
  485.     else if ( mShowGrid || inForceErase )
  486.         ::EraseRect( &inEraseRect );
  487. }
  488.  
  489. // ---------------------------------------------------------------------------
  490. //        • CalculateGridRect (PRIVATE)
  491. //
  492. //          Called by:    CGraphPane::ObeyCommand
  493. //                        CGraphPane::DrawTheBest
  494. // ---------------------------------------------------------------------------
  495.  
  496. void
  497. CGraphPane::CalculateGridRect( )
  498. {
  499.     mGridRect = mFrameRect;
  500.     ::InsetRect( &mGridRect, 1, 1 );
  501.  
  502.     Int16    theGridWidth = (mApp -> GetGridSize()) * mGridSquareSize + 2;
  503.  
  504.     Int16    theInset     = (mGridRect.right - mGridRect.left + 1
  505.                                 - theGridWidth) / 2;
  506.  
  507.     ::InsetRect( &mGridRect, theInset, theInset);
  508.  
  509.     if ( theGridWidth % 2 ) {
  510.         ++mGridRect.right;
  511.         ++mGridRect.bottom;
  512.     }
  513. }
  514.  
  515. // ---------------------------------------------------------------------------
  516. //        • DrawGrid (PRIVATE)
  517. //
  518. //          Called by:    CGraphPane::CreatePict
  519. //                        CGraphPane::DrawTheBest
  520. // ---------------------------------------------------------------------------
  521.  
  522. void
  523. CGraphPane::DrawGrid()
  524. {
  525.     const RGBColor    frameRGB        = { 0x1F74, 0xFFFF, 0x088A };
  526.     const RGBColor  dark_gridRGB    = { 0x04A7, 0x1D10, 0x02AC };    
  527.     const RGBColor  bright_gridRGB    = { 0x0A05, 0x3E90, 0x05C1 };    
  528.  
  529.     Rect  theInnerFrame = mGridRect;
  530.     
  531.     ::InsetRect( &theInnerFrame, 1, 1);    
  532.  
  533.     // Draw first the box...
  534.  
  535.     if ( mUseColor )    
  536.             ::RGBForeColor( &frameRGB );
  537.     else    ::RGBForeColor( &d_greyRGB );
  538.             
  539.     ::PenNormal();
  540.     ::FrameRect( &mGridRect );
  541.     
  542.     if ( mUseColor ) {
  543.         if (mDarkGrid)        
  544.                 ::RGBForeColor( &dark_gridRGB );
  545.         else    ::RGBForeColor( &bright_gridRGB );
  546.     }
  547.     else    ::RGBForeColor( &l_greyRGB );
  548.         
  549.     ::FrameRect( &theInnerFrame);    // And this is the one inside mGridRect
  550.         
  551.     // ...and then the grid... 
  552.  
  553.     Int16    theLeft     = mGridRect.left, 
  554.             theTop         = mGridRect.top,
  555.             theRight    = mGridRect.right,
  556.             theBottom     = mGridRect.bottom,
  557.             theGridSize = mApp -> GetGridSize(),
  558.             theX, theY,
  559.             theDex;
  560.  
  561.     ::PenSize( 2,2 );
  562.  
  563.     for ( theDex = 1; theDex < theGridSize; ++theDex ) {
  564.     
  565.         theX = theY    = theLeft + (theDex * mGridSquareSize);
  566.     
  567.         LineFromTo (     theX,            // xFrom
  568.                         theTop + 1,        // yFrom
  569.                         theX,            // xTo
  570.                         theBottom - 3);    // yTo
  571.  
  572.         LineFromTo (     theLeft + 1,    // xFrom
  573.                         theY,            // yFrom
  574.                         theRight - 3,    // xTo
  575.                         theY);            // yTo
  576.     }
  577. }
  578.  
  579. // ---------------------------------------------------------------------------
  580. //        • DrawEdges (PRIVATE)
  581. //
  582. //          Called by:    CGraphPane::CreatePict
  583. //                        CGraphPane::DrawTheBest
  584. // ---------------------------------------------------------------------------
  585.  
  586. void
  587. CGraphPane::DrawEdges( Boolean inDrawToPict )
  588. {
  589.     Int16    theOneOneXY = mGridRect.left + (mGridSquareSize / 2) + 1;
  590.  
  591.     ::PenNormal();
  592.  
  593.     if ( mUseColor )                        // Set edge color
  594.         ::RGBForeColor( &goldenRGB );
  595.     else    
  596.         if ( inDrawToPict )
  597.                 ::RGBForeColor( &blackRGB );    // black to pict
  598.         else    ::RGBForeColor( &D_greyRGB );    // very dark grey on screen
  599.     
  600.     mGraph -> DrawEdges( theOneOneXY, mGridSquareSize );
  601. }
  602.  
  603. // ---------------------------------------------------------------------------
  604. //        • DrawNodes (PRIVATE)
  605. //
  606. //          Called by:    CGraphPane::CreatePict
  607. //                        CGraphPane::DrawTheBest
  608. // ---------------------------------------------------------------------------
  609.  
  610. void
  611. CGraphPane::DrawNodes()
  612. {
  613.     const     RGBColor   nodeRGB = { 0xBDBD, 0x0000, 0x0000 };    // = Red
  614.  
  615.     Rect    theOneOneRect;
  616.  
  617.     // We first set the rect to the upper left corner of 
  618.     // the (1,1) square. The size is set according to mNodeSize.
  619.  
  620.     ::SetRect(     &theOneOneRect, 
  621.                 mGridRect.left + 1,                    // Left
  622.                 mGridRect.top  + 1,                    // Top
  623.                 mGridRect.left + 1 + mNodeSize,        // Right
  624.                 mGridRect.top  + 1 + mNodeSize);    // Bottom
  625.  
  626.     // We then shift the rect to the middle of the square...
  627.  
  628.     Int16    theOffset = (mGridSquareSize - mNodeSize) / 2;
  629.  
  630.     ::OffsetRect( &theOneOneRect, theOffset, theOffset);
  631.  
  632.     if ( mUseColor )                        // Set node color
  633.             ::RGBForeColor( &nodeRGB );
  634.     else    ::RGBForeColor( &blackRGB );    
  635.  
  636.     ::PenNormal();
  637.  
  638.     mGraph -> DrawNodes( theOneOneRect, mGridSquareSize);
  639. }
  640.  
  641. // ---------------------------------------------------------------------------
  642. //        • SelectNodeSize (PRIVATE)
  643. //
  644. //          Called by:    CGraphPane::ObeyCommand
  645. //                        CGraphPane::SetGraph
  646. // ---------------------------------------------------------------------------
  647.  
  648. Int16
  649. CGraphPane::SelectNodeSize()
  650. {
  651.     if ( mGridSquareSize < 10 )        return mGridSquareSize - 2;
  652.     if ( mGridSquareSize < 14 )        return mGridSquareSize - 4;
  653.     if ( mGridSquareSize < 17 )        return mGridSquareSize - 6;
  654.     if ( mGridSquareSize < 21 )        return mGridSquareSize - 8;
  655.     if ( mGridSquareSize < 24 )        return 11;
  656.     if ( mGridSquareSize < 29 )        return 12;
  657.     if ( mGridSquareSize < 31 )        return 13;
  658.     if ( mGridSquareSize < 38 )        return 15;
  659.     
  660.     switch ( mGridSquareSize ) {
  661.     
  662.         case 38:     return 18;    break;
  663.         case 42:     return 20;    break;
  664.         case 49:     return 25;    break;
  665.         case 57:     return 27;    break;
  666.         case 67:     return 31;    break;
  667.         case 85:     return 41;    break;
  668.         case 113:     return 55;    break;
  669.         case 173:     return 85;    break;
  670.         
  671.         default:    return 0;    // Should never happen...
  672.     }
  673. }
  674.  
  675. // ---------------------------------------------------------------------------
  676. //        • GetNextSquareSize (PRIVATE)
  677. //
  678. //          Called by:    CGraphPane::ObeyCommand
  679. // ---------------------------------------------------------------------------
  680.  
  681. Int16
  682. CGraphPane::GetNextSquareSize( Boolean inBigger )
  683. {
  684.     Int16    *theScanner = kSquareSizes;
  685.  
  686.     while ( *theScanner != mGridSquareSize )
  687.         theScanner++;
  688.         
  689.     if ( inBigger )
  690.             theScanner++;
  691.     else     theScanner--;
  692.     
  693.     return *theScanner;
  694. }
  695.  
  696. // ---------------------------------------------------------------------------
  697. //        • ValidSquareSize (PRIVATE)
  698. //
  699. //          Called by:    CGraphPane::ObeyCommand
  700. // ---------------------------------------------------------------------------
  701.  
  702. Boolean
  703. CGraphPane::ValidSquareSize( Int16 inSize )
  704. {
  705.     Int16    *theScanner = kSquareSizes;
  706.  
  707.     if ( inSize < 5 || inSize > mMaxSquareSize )
  708.         return false;
  709.     else {
  710.         
  711.         while ( *theScanner < inSize )
  712.             theScanner++;
  713.         
  714.         return (*theScanner == inSize);
  715.     }
  716. }
  717.